package com.ikingtech.platform.service.system.dept.service.repository;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ikingtech.framework.sdk.base.model.DictItem;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.department.api.DeptDictApi;
import com.ikingtech.framework.sdk.department.api.DeptUserApi;
import com.ikingtech.framework.sdk.department.model.DeptBasicDTO;
import com.ikingtech.framework.sdk.department.model.DeptDTO;
import com.ikingtech.framework.sdk.department.model.DeptManagerDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.system.dept.entity.DepartmentDO;
import lombok.RequiredArgsConstructor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
public class ModelConverter {

    private final DeptRepository repo;

    private final DeptUserApi deptUserApi;

    private final DeptDictApi deptDictApi;

    public List<DeptBasicDTO> modelInfoConvert(List<DepartmentDO> entities) {
        Map<String, DictItem> categoryMap = this.deptDictApi.load(Tools.Coll.convertList(entities, DepartmentDO::getCategory), Me.tenantCode());
        return Tools.Coll.convertList(entities, entity -> this.modelInfoConvert(entity, categoryMap.get(entity.getCategory())));
    }

    public List<DeptDTO> modelConvert(List<DepartmentDO> entities, List<String> dataScope, Boolean dataScopeOnly) {
        if (Tools.Coll.isBlank(entities)) {
            return new ArrayList<>();
        }
        List<DepartmentDO> subEntities = this.repo.list(
                Wrappers.<DepartmentDO>lambdaQuery()
                        .and(wrapper -> Tools.Coll.convertList(entities, DepartmentDO::getFullPath).forEach(fullPath -> wrapper.or().likeRight(DepartmentDO::getFullPath, fullPath)))
                        .orderByDesc(DepartmentDO::getCreateTime)
        );
        Map<String, Integer> userCountMap = this.deptUserApi.getUserCount(
                Tools.Coll.convertList(subEntities,
                        entity -> !Boolean.TRUE.equals(dataScopeOnly) ||
                                Tools.Coll.isBlank(dataScope) ||
                                dataScope.contains(entity.getId()),
                        DepartmentDO::getId));
        List<DeptManagerDTO> managers = this.deptUserApi.loadManagers(Tools.Coll.convertList(entities, DepartmentDO::getManagerId));
        Map<String, DeptManagerDTO> managerMap = Tools.Coll.convertMap(managers, DeptManagerDTO::getUserId, manager -> manager);
        List<DepartmentDO> unities = this.repo.findUnities(entities);
        Map<String, DictItem> categoryMap = this.deptDictApi.load(Tools.Coll.convertList(entities, DepartmentDO::getCategory), Me.tenantCode());
        return Tools.Coll.convertList(entities, entity -> {
            List<String> subEntityIds = Tools.Coll.flatMap(
                    Tools.Coll.filter(subEntities,
                            subEntity -> subEntity.getFullPath().startsWith(entity.getFullPath())),
                    subEntity -> Tools.Str.split(subEntity.getFullPath().substring(subEntity.getFullPath().indexOf(subEntity.getId())), "@"),
                    Collection::stream
            );
            DepartmentDO unity = null;
            for (DepartmentDO unityEntity : unities) {
                if (entity.getFullPath().contains(unityEntity.getId())) {
                    unity = unityEntity;
                    break;
                }
            }
            return this.modelConvert(entity,
                    unity,
                    managerMap.get(entity.getManagerId()),
                    Tools.Coll.mapFilter(userCountMap, entry -> subEntityIds.contains(entry.getKey())),
                    categoryMap.get(entity.getCategory()));
        });
    }

    public DeptDTO modelInfoConvert(DepartmentDO entity, DictItem category) {
        DeptDTO dept = this.modelInfoConvert(entity);
        dept.setCategoryInfo(category);
        return dept;
    }

    public DeptDTO modelInfoConvert(DepartmentDO entity) {
        DeptDTO dept = Tools.Bean.copy(entity, DeptDTO.class);
        if (null != dept.getType()) {
            dept.setTypeName(dept.getType().description);
        }
        if (null != dept.getStatus()) {
            dept.setStatusName(dept.getStatus().description);
        }
        if (null != dept.getEquityRatio()) {
            dept.setEquityRatioName(dept.getEquityRatio().description);
        }
        if (null != dept.getIntroductionType()) {
            dept.setIntroductionTypeName(dept.getIntroductionType().description);
        }
        return dept;
    }

    public DeptDTO modelConvert(DepartmentDO entity,
                                DepartmentDO unity,
                                DeptManagerDTO manager,
                                Map<String, Integer> userCountMap,
                                DictItem category) {
        DeptDTO dept = this.modelInfoConvert(entity, category);
        dept.setManager(manager);
        dept.setUserCount(Tools.Coll.mapSum(userCountMap));
        dept.setInDataScope(Tools.Coll.isBlank(Me.dataScope()) || Me.dataScope().contains(dept.getId()));
        dept.setUnity(null == unity ? null : Tools.Bean.copy(unity, DeptDTO.class));
        dept.setCategoryInfo(category);
        return dept;
    }
}
